package com.itheima.reggie.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.entity.SetmealDish;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import com.itheima.reggie.service.SetmealDishService;
import com.itheima.reggie.utils.RedisKeys;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author kcs
 * @date 2021/11/24
 * @TIME:16:21
 */
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SetmealDishService setmealDishService;

    /**
     * 添加菜品
     * @param dishDto
     */
    @Override
    public void addDish(DishDto dishDto) {

        //1.添加菜品,获得添加后的菜品id
        //包含一个功能,添加成功后把添加的主键id设置到对象中
        this.save(dishDto);

        //2.取出所有口味数据
        List<DishFlavor> flavors = dishDto.getFlavors();

        //3.为每个口味添加菜品id
        //获取菜品id
        Long dishId = dishDto.getId();

        //4.循环设置到口味对象中
        /*for (DishFlavor flavor : flavors) {
            flavor.setId(dishId);
        }*/
        flavors.stream().forEach(c->c.setDishId(dishId));//lambda表达式

        //5.保存到数据库中
        dishFlavorService.saveBatch(flavors);

        //6.删除redis中当前分类的菜品信息
        redisTemplate.delete(RedisKeys.DISH+dishDto.getCategoryId()+"_1");

    }

    /**
     * 分页+条件查询菜品信息
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public IPage<DishDto> findByPage(Integer page, Integer pageSize, String name) {

        //设置分页条件
        IPage<Dish> pageInfo = new Page<>(page,pageSize);
        //设置搜索条件
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        if(null != name && name != ""){
            wrapper.like(Dish::getName,name);
        }
        //设置排序条件
        wrapper.eq(Dish::getIsDeleted,0);
        wrapper.orderByDesc(Dish::getUpdateTime);
        IPage<Dish> iPage = page(pageInfo, wrapper);

        //把原有的Dish对象重新封装一个DishDto对象
        List<Dish> dishes = iPage.getRecords();
        List<DishDto> dishDtos = JSON.parseArray(JSON.toJSONString(dishes),DishDto.class);

        //设置DishDto中的CategoryName值 -- lambda (for循环也可)
        dishDtos = dishDtos.stream().map((c)->{
            //根据分类id 查询分类名称
            Long categoryId = c.getCategoryId();//获得分类id
            //把分类的名字设置给dto对象
            Category category = categoryService.getById(categoryId);
            c.setCategoryName(category.getName());
            return c;
        }).collect(Collectors.toList());

        //封装到一个新的page对象中并返回
        IPage<DishDto> dtoPage = new Page<>();
        dtoPage.setTotal(iPage.getTotal());
        dtoPage.setRecords(dishDtos);
        return dtoPage;
    }

    /**
     * 根据菜品id查询菜品信息和对应的口味信息 -- 回显功能
     * @param id
     * @return
     */
    @Override
    public DishDto get(Long id) {

        //数据校验
        if(id == null){
            return null;
        }

        //1.查询菜品信息
        Dish dish = this.getById(id);

        //2.查询口味信息
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId,dish.getId());
        List<DishFlavor> dishFlavors = dishFlavorService.list(wrapper);

        //3.将所有信息封装到一个dishDto对象
        DishDto dishDto = new DishDto();
        //Bean拷贝
        BeanUtils.copyProperties(dish,dishDto);
        dishDto.setFlavors(dishFlavors);

        return dishDto;
    }

    /**
     * 修改菜品信息 菜品表 + 口味表
     * @param dishDto
     */
    @Override
    public void updateDish(DishDto dishDto) {
        //1.修改菜品信息
        this.updateById(dishDto);

        //2.修改口味表信息 -- 先删除,后添加
        //2.1 先删除原来口味
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId,dishDto.getId());
        dishFlavorService.remove(wrapper);

        //2.2 再添加口味
        List<DishFlavor> flavors = dishDto.getFlavors().stream().map((c) -> {
            c.setDishId(dishDto.getId());
            return c;
        }).collect(Collectors.toList());
        dishFlavorService.saveBatch(flavors);

        //删除redis中的菜品缓存信息
        Set keys = redisTemplate.keys(RedisKeys.DISH + "*");
        redisTemplate.delete(keys);

        //saveOrUpdateBatch 判断是否存在主键id 进行修改或者新增
        //dishFlavorService.saveOrUpdateBatch(flavors);

    }

    /**
     * (批量)起售/停售状态修改
     * @param status
     * @param ids
     */
    @Override
    public void updateStatus(Integer status, Long[] ids) {

        //1.查询出需要修改状态的dish集合
        List<Dish> dishes = this.listByIds(Arrays.asList(ids));

        //2.设置状态
        dishes = dishes.stream().map((c)->{
            c.setStatus(status);
            return c;
        }).collect(Collectors.toList());

        //3.在数据库中进行修改
        this.updateBatchById(dishes);

        //删除redis中的菜品缓存信息
        Set keys = redisTemplate.keys(RedisKeys.DISH + "*");
        redisTemplate.delete(keys);
    }

    /**
     * 删除菜品 -- 删除之前需要先判断(逻辑删除)
     * @param ids
     */
    @Override
    public R delete(Long[] ids) {

        //1.根据删除菜品的ID，查询该菜品下是否存在口味数据，如果存在，删除口味
        for (Long id : ids) {
            LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DishFlavor::getDishId,id);
            List<DishFlavor> dishFlavors = dishFlavorService.list(wrapper);
            if(dishFlavors != null){
                dishFlavorService.removeById(id);
            }
        }

        //2.根据删除菜品的ID，查询该菜品是否属于套餐，如果属于，则提示错误信息
        for (Long id : ids) {
            LambdaQueryWrapper<SetmealDish> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SetmealDish::getDishId,id);
            List<SetmealDish> setmealDishes = setmealDishService.list(wrapper);
            System.out.println(setmealDishes);
            if(setmealDishes.size() > 0){
                return R.error("菜品属于套餐,不能删除");
            }
        }

        //3.执行正常的删除菜品操作
        List<Dish> dishes = this.listByIds(Arrays.asList(ids));
        dishes = dishes.stream().map(c->{
            c.setIsDeleted(1);
            return c;
        }).collect(Collectors.toList());
        this.updateBatchById(dishes);

        //删除redis中的菜品缓存信息
        Set keys = redisTemplate.keys(RedisKeys.DISH + "*");
        redisTemplate.delete(keys);

        return R.success("删除成功");
    }

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据分类查询菜品
     * @param dish
     * @return
     */
    @Override
    public List<DishDto> getDishesByCategoryId(Dish dish) {

        //0.判断redis中是否存在数据
        String key = RedisKeys.DISH+dish.getCategoryId()+"_"+dish.getStatus();
        List<DishDto> dishDtos = (List<DishDto>) redisTemplate.opsForValue().get(key);

        //若存在,直接返回
        if(dishDtos != null && dishDtos.size() != 0){
            return  dishDtos;
        }

        //若不存在,进行数据库查询
        //1.查询菜品
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Dish::getCategoryId,dish.getCategoryId())
                .eq(dish.getStatus() != null,Dish::getStatus,dish.getStatus());
        List<Dish> dishes = this.list(wrapper);

        //2.查询口味
        dishDtos = JSON.parseArray(JSON.toJSONString(dishes),DishDto.class);

        //2.1设置CategoryName
        dishDtos = dishDtos.stream().map((c)->{
            //根据分类id 查询分类名称
            Long categoryId = c.getCategoryId();//获得分类id
            //把分类的名字设置给dto对象
            Category category = categoryService.getById(categoryId);
            c.setCategoryName(category.getName());
            return c;
        }).collect(Collectors.toList());

        //2.2 设置口味信息
        for (DishDto dishDto : dishDtos) {
            LambdaQueryWrapper<DishFlavor> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(DishFlavor::getDishId,dishDto.getId());
            List<DishFlavor> dishFlavors = dishFlavorService.list(wrapper1);
            dishDto.setFlavors(dishFlavors);
        }

        //将查询到的数据存储到redis中,设置缓存时间30分钟
        redisTemplate.opsForValue().set(key,dishDtos,30, TimeUnit.MINUTES);
        return dishDtos;
    }
}
